package ru.ifmo.mlarinsky.classificator.map;

import ru.ifmo.mlarinsky.classificator.classification.Classification;
import ru.ifmo.mlarinsky.classificator.math.MathUtil;
import ru.ifmo.mlarinsky.classificator.model.Instrument;

import java.util.List;
import ru.ifmo.mlarinsky.classificator.model.Vector;
import ru.ifmo.mlarinsky.classificator.providers.InstructionsProvider;
import ru.ifmo.mlarinsky.classificator.providers.ReturnHistoryVectorProvider;

public class MapDeterminationPainter extends MapPainter {
    private ReturnHistoryVectorProvider vectorProvider;

    private final Classification classification;

    public MapDeterminationPainter(Classification classification) {
        this.classification = classification;
    }

    @Override
    void paintNode(MapNode mapNode) {
        String indexSymbol = getIndex(mapNode).getSymbol();
//        double[] values = mapNode.getValues();
//        String[] dimensions = mapNode.getDimensions();
//
//        Map<String, Double> mapNodeValues = new HashMap<String, Double>();
//        Map<String, Double> realValues = new HashMap<String, Double>();
//
//        String label = mapNode.getLabel();
//        if (label.contains("YHOO")) {
//            int i = 0;
//            for (String dimension : dimensions) {
//                mapNodeValues.put(dimension, values[i++]);
//            }
//
//            Instrument ibm = InstrumentRegister.getInstrument("YHOO");
//            QuoteDate firstQuoteDate = new QuoteDate(new Date(
//                    QuoteDate.valueOf(dimensions[0]).getTime() - 1000 * 60 * 60 * 24));
//            Quote prevQuote = ibm.getQuote(firstQuoteDate);
//            for (String dimension : dimensions) {
//                QuoteDate quoteDate = QuoteDate.valueOf(dimension);
//                Quote currQuote = ibm.getQuote(quoteDate);
//
//                realValues.put(dimension, MathUtil.returnRate(prevQuote, currQuote));
//                prevQuote = currQuote;
//            }
//
//            int sum = 0;
//            for (String dimension : realValues.keySet()) {
//                int dif = MathUtil.percent(realValues.get(dimension) / mapNodeValues.get(dimension));
//                sum += dif;
//                System.out.println(dimension + " - " + dif);
//            }
//
//            System.out.println("SUM = " + sum / dimensions.length);
//            System.out.println("Index = " + getIndex(mapNode).getSymbol());
//        }

        mapNode.setColor(classification.getIndexColor(indexSymbol));
        mapNode.setValue(classification.getIndexSector(indexSymbol));
    }

    @Override
    void preprocessMap(SomMap map) {
        validateMap(map);

        vectorProvider = (ReturnHistoryVectorProvider) map.getInstructionsProvider().getVectorProvider();
    }

    private void validateMap(SomMap map) {
        IllegalStateException validationFailedException = new IllegalStateException("Map validation failed");

        InstructionsProvider instructionsProvider = map.getInstructionsProvider();
        if (instructionsProvider == null) {
            throw validationFailedException;
        }

        if (!(instructionsProvider.getVectorProvider() instanceof ReturnHistoryVectorProvider)) {
            throw validationFailedException;
        }
    }

    private Instrument getIndex(MapNode node) {
        double[] nodeReturnRates = node.getValues();

        double maxDetermination = 0;
        Instrument sectorIndex = null;

        List<Instrument> indexes = classification.getIndexes();
        for (Instrument index : indexes) {
            Vector vector = vectorProvider.getVector(index);
            Double[] indexReturnRates = vector.getValues();

            double determination = MathUtil.determination(
                    MathUtil.boxDoubleArray(nodeReturnRates), indexReturnRates);

            if (determination > maxDetermination) {
                maxDetermination = determination;
                sectorIndex = index;
            }
        }

        return sectorIndex;
    }
}
